﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Metadata.Edm;
using System.Web.Mvc;

namespace SoftHotel.Models
{
    public class ReservaHabDAO : DbContext
    {
        /* Esta clase va a representar el EF
         * como detalle reserva esta incluido dentro de reserva
         * dentro de este DAO vamos a manejar la conexión a ambas tablas
         */

        public DbSet<ReservaHab> reservas { get; set; }
        public DbSet<DetalleReservaHab> detalles { get; set; }

        public ListaPreciosDAO listaPrecio = new ListaPreciosDAO();
        public AmbienteDAO ambiente = new AmbienteDAO();
            
        public List<ReservaHab> reservaslista= new List<ReservaHab>() { };
        public List<ReservaHab> busquedares = new List<ReservaHab>() { };

        public ReservaHabDAO():base("conexionPrincipalDAO"){}
        private Conexion conexionBD = new Conexion();
     
        /* Este metodo de override es para indicarle al EF
         * que el nombre de la tabla es distinto del nombre de la clase
         */
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ReservaHab>().ToTable("Reserva");
            modelBuilder.Entity<Cliente>().ToTable("Cliente"); //Mono!!
            modelBuilder.Entity<Parametro>().ToTable("Parametro"); //Mono!!
            modelBuilder.Entity<Ambiente>().ToTable("Ambiente"); //Mono!!!
            modelBuilder.Entity<DetalleReservaHab>().ToTable("DETALLERESERVA");//MONO!!
        }

        /*************************************************** RESERVA *************************************************************/

        public void Agregar(ReservaHab reserva)
        {
            reserva.numeroReserva = generarNumero();
            reserva.fechaCreacion = DateTime.Now.Date;
            reserva.tipo = 0;
            reserva.estado = 0;
            ActulizarEstado(reserva);
            reservas.Add(reserva);
            this.SaveChanges();
        }

        public ReservaHab Buscar(int idReserva)
        {
            var res = reservas.Where(g => g.idReserva == idReserva);
            List<ReservaHab> reserva = new List<ReservaHab>();
            reserva = res.ToList();
            if (reserva != null)
                return reserva[0];
            
            return null;
        }

        public List<ReservaHab> Buscar(ReservaHab reserva)
        {
            var res = reservas.Where(g => g.numeroReserva.ToUpper().Contains(reserva.numeroReserva));
            return res.ToList();
        }

        public void Editar(ReservaHab reserva)
        {
            this.Entry(reserva).State = EntityState.Modified;
            this.SaveChanges();
        }

        public void Checkin(ReservaHab reserva)
        {
            reserva.fechaCheckin2 = DateTime.Now;
            reserva.estado = 2;
            ActulizarEstado(reserva);
            this.Entry(reserva).State = EntityState.Modified;
            this.SaveChanges();
        }

        public void Checkout(ReservaHab reserva)
        {
            reserva.fechaCheckout2 = DateTime.Now;
            reserva.estado = 3;
            ActulizarEstado(reserva);
            this.Entry(reserva).State = EntityState.Modified;
            this.SaveChanges();
        }

        /* Las reservas no se pueden eliminar solo se anulan.
         * Para el caso del detalle es posible eliminarlo y anular dependiendo el contexto.
         */

        public void Anular(ReservaHab reserva)
        {
            reserva.estado = 4;
            ActulizarEstado(reserva);
            this.Entry(reserva).State = EntityState.Modified;
            this.SaveChanges();
        }

        public void ActulizarEstado(ReservaHab reserva)
        {
            switch (reserva.estado)
            {
                case 0: reserva.nombreEstado = "Reservada"; break;
                case 1: reserva.nombreEstado = "Confirmada"; break;
                case 2: reserva.nombreEstado = "Iniciada"; break;
                case 3: reserva.nombreEstado = "Finalizada"; break;
                case 4: reserva.nombreEstado = "Anulada"; break;
            }
        }

        public void CalcularTotal(ReservaHab reserva)
        {
            var det = detalles.Where(g => g.idReserva == reserva.idReserva);
            Decimal total = 0;
            foreach (var item in det)
            {
                total = total + item.total;
            }

            reserva.total = total;
        }

        public string generarNumero()
        {
            String consulta = "SELECT SUBSTRING(MAX(numeroReserva),4,7) FROM RESERVA";
            SqlDataReader dataReader = conexionBD.EjecutarReader(consulta);
            dataReader.Read();
            string aux = dataReader[0] + "";
            int r;
            if (aux == "") r = 1;
            else r = Convert.ToInt32(aux) + 1;

            string id = r.ToString();
            int nrodig = id.Length;

            for (int i = 1; i <= 7 - nrodig; i++)
                id = "0" + id;
            id = "RES" + id;
            dataReader.Close();
            return id;
        }  

        /******************************************** DETALLE RESERVA *************************************************************/

        public void AgregarDetalle(DetalleReservaHab detalle)
        {
            /* Selecciono el tipo de ambiente de la tabla Ambiente a través de su id
             * Luego con el tipo de ambiente lo busco en la tabla DetallePrecio
             */
            //var amb = ambiente.ambientes.Where(g => g.idAmbiente == detalle.idAmbiente);
            //List<Ambiente> ambientes = new List<Ambiente>();                        
            //ambientes = amb.ToList();

            //var precio = listaPrecio.DetallesPrecio.Where(a => a.tipoAmbiente == ambientes[0].tipoAmbiente);
            //List<DetallePrecio> precios = new List<DetallePrecio>();
            //precios = precio.ToList();

            //if (precios != null)
            //{
            //    detalle.precioUnitario = precios[0].precio;
            //    detalle.total = detalle.precioUnitario * detalle.cantidad;
            //}

            var res = reservas.Where(a => a.idReserva == detalle.idReserva);
            List<ReservaHab> reserva = new List<ReservaHab>();
            reserva = res.ToList();

            detalle.precioUnitario = BuscarPrecio(detalle);
            detalle.total = detalle.precioUnitario * detalle.cantidad;
            detalle.duracion = 1;
            detalle.estado = 58;
            //detalle.duracion = CalcularDuracion(reserva[0].fechaCheckout, reserva[0].fechaCheckin);
            //detalle.estado

            detalles.Add(detalle);
            this.SaveChanges();
        }

        public void EditarDetalle(DetalleReservaHab detalle)
        {
            this.Entry(detalle).State = EntityState.Modified;
            this.SaveChanges();
        }

        public List<DetalleReservaHab> BuscarDetalle(int idReserva)
        {
            var det = detalles.Where(g => g.idReserva == idReserva);
            return det.ToList();
                 
        }

        public DetalleReservaHab BuscarDetalleID(int idDetalleReserva)
        {
            var det = detalles.Where(g => g.idDetalleReserva == idDetalleReserva);
            List<DetalleReservaHab> detalle = new List<DetalleReservaHab>();
            detalle = det.ToList();

            if (detalle != null)
                return detalle[0];
            return null;

        }

        public void AnularDetalle(DetalleReservaHab detalle)
        {
            detalle.estado = 4; //validar cual es el estado anulado
            this.Entry(detalle).State = EntityState.Modified;
            this.SaveChanges();
        }

        public void EliminarDetalle(DetalleReservaHab detalle)
        {
            this.Entry(detalle).State = EntityState.Deleted;
            this.SaveChanges();
        }

        public int CalcularDuracion(DateTime fechaI, DateTime fechaF)
        {
            int duracion = 0;
            TimeSpan dur = DateTime.Now.Subtract(fechaF).Subtract(DateTime.Now.Subtract(fechaI));

            duracion = Convert.ToInt32(dur.ToString());
            return duracion;
        }

        public Decimal BuscarPrecio(DetalleReservaHab detalle)
        {
            AmbienteDAO ambDAO = new AmbienteDAO();
            string id = detalle.idAmbiente.ToString();

            String consulta = "";
            consulta = "SELECT idAmbiente, idSede, nombre, tipoAmbiente, piso, disponible, capacidad, descripcion, estado FROM AMBIENTE WHERE idAmbiente = \'" + id + "\'";
            conexionBD.AbrirConexion();
            SqlDataReader dataReader = conexionBD.EjecutarReader(consulta);

            Ambiente amb = new Ambiente();
            while (dataReader != null && dataReader.Read())
            {
                amb.idAmbiente = Convert.ToInt32(dataReader[0].ToString());
                amb.idSede = Convert.ToInt32(dataReader[1].ToString());
                amb.nombre = dataReader[2].ToString();
                amb.tipoAmbiente = Convert.ToInt32(dataReader[3].ToString());
                amb.piso = Convert.ToInt32(dataReader[4].ToString());
                amb.disponible = Convert.ToBoolean(dataReader[5].ToString());
                amb.descripcion = dataReader[6].ToString();
            }
            dataReader.Close();


            string consulta1 = "";
            consulta1 = "SELECT precio FROM DetallePrecio WHERE tipoambiente = @tipo ";

            SqlDataReader dataReader1 = null;
            conexionBD.AbrirConexion();
            SqlCommand command = conexionBD.connection.CreateCommand();
            command.CommandText = consulta1;
            command.Parameters.Add("@tipo", SqlDbType.Int).Value = amb.tipoAmbiente;

            dataReader1 = command.ExecuteReader();

            dataReader1.Read();

            if (!dataReader1.HasRows) return 0;
            else return dataReader1.GetDecimal(0);

        }

    }
}